package com.example.gpsparse;

import com.example.gpsparse.dao.GpsDataDao;
import com.example.gpsparse.model.AmapResponse;
import com.example.gpsparse.model.GpsData;
import com.example.gpsparse.service.AmapService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * GPS解析服务
 */
@Service
public class GpsParseService {

    private static final Logger logger = LoggerFactory.getLogger(GpsParseService.class);

    @Autowired
    private GpsDataDao gpsDataDao;

    @Autowired
    private AmapService amapService;

    @Value("${batch.size}")
    private int batchSize;

    /**
     * 处理GPS数据
     *
     * @return 处理的记录数
     */
    public int processGpsData() {
        int totalProcessed = 0;
        boolean hasMoreData = true;

        // 创建线程池，用于并行处理API请求
        // 线程数设置为可用处理器数量的2倍，但不超过10个线程
        int threadCount = Math.min(Runtime.getRuntime().availableProcessors() * 2, 10);
        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
        logger.info("创建线程池，线程数: {}", threadCount);

        try {
            while (hasMoreData) {
                // 查询未处理的GPS数据
                List<GpsData> gpsDataList = gpsDataDao.findUnprocessedGpsData(batchSize);
                
                if (gpsDataList.isEmpty()) {
                    logger.info("没有更多未处理的GPS数据");
                    hasMoreData = false;
                    break;
                }

                logger.info("获取到{}条未处理的GPS数据", gpsDataList.size());

                // 并行处理每条GPS数据
                List<CompletableFuture<Void>> futures = new ArrayList<>();
                for (GpsData gpsData : gpsDataList) {
                    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                        try {
                            processGpsDataItem(gpsData);
                        } catch (Exception e) {
                            logger.error("处理GPS数据异常，ID: {}", gpsData.getId(), e);
                            gpsData.setStatus(2); // 处理失败
                            gpsData.setErrorMsg("处理异常: " + e.getMessage());
                        }
                    }, executorService);
                    futures.add(future);
                }

                // 等待所有任务完成
                CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

                // 批量更新数据库
                int updated = gpsDataDao.batchUpdateGpsAddress(gpsDataList);
                totalProcessed += updated;
                logger.info("批量更新{}条GPS数据到数据库", updated);

                // 如果返回的数据少于批次大小，说明没有更多数据了
                if (gpsDataList.size() < batchSize) {
                    hasMoreData = false;
                }
            }
        } finally {
            // 关闭线程池
            executorService.shutdown();
            try {
                if (!executorService.awaitTermination(30, TimeUnit.SECONDS)) {
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }

        return totalProcessed;
    }

    /**
     * 处理单条GPS数据
     *
     * @param gpsData GPS数据
     */
    private void processGpsDataItem(GpsData gpsData) {
        logger.debug("处理GPS数据，ID: {}, 经度: {}, 纬度: {}", 
                gpsData.getId(), gpsData.getLongitude(), gpsData.getLatitude());

        // 调用高德地图API获取地址信息
        AmapResponse amapResponse = amapService.getAddressByLocation(
                gpsData.getLongitude(), gpsData.getLatitude());

        if (amapResponse.isSuccess() && amapResponse.getRegeocode() != null) {
            // 解析地址信息
            AmapResponse.ReGeocode regeocode = amapResponse.getRegeocode();
            AmapResponse.AddressComponent addressComponent = regeocode.getAddressComponent();

            gpsData.setAddress(regeocode.getFormattedAddress());
            gpsData.setProvince(addressComponent.getProvince());
            gpsData.setCity(addressComponent.getCity());
            gpsData.setDistrict(addressComponent.getDistrict());
            
            // 获取街道信息
            if (addressComponent.getStreet() != null) {
                gpsData.setStreet(addressComponent.getStreet().getFullStreet());
            } else {
                gpsData.setStreet(addressComponent.getTownship());
            }
            
            gpsData.setStatus(1); // 处理成功
            logger.debug("解析成功，地址: {}", gpsData.getAddress());
        } else {
            // 解析失败
            gpsData.setStatus(2); // 处理失败
            gpsData.setErrorMsg("API响应失败: " + amapResponse.getInfo());
            logger.warn("解析失败，ID: {}, 错误: {}", gpsData.getId(), amapResponse.getInfo());
        }
    }
}